﻿using diary.POCO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Text;
using System.Threading.Tasks;
using NLog;

namespace diary.DAL
{
    public class DiaryLoader
    {
        private DateTime _currentDate = DateTime.Now;
        private Logger logger = LogManager.GetCurrentClassLogger();

        public Diary LoadDiary()
        {
            Diary diary = new Diary();
            XmlDocument docDiary = new XmlDocument();
            try
            {

                logger.Log(LogLevel.Info, "Loading " + Constants.FILE_DIARY);
                docDiary.Load(Constants.FILE_DIARY);

                diary.Version = docDiary.DocumentElement.Attributes["version"].Value;
                logger.Log(LogLevel.Info, "Loading section all-time best");
                diary.Best = LoadBest(docDiary.DocumentElement.SelectSingleNode("best"));
                logger.Log(LogLevel.Info, "Loading section years");
                diary.Years = LoadYears(docDiary.DocumentElement);
            }
            catch(Exception ex)
            {
                logger.Log(LogLevel.Error, "Unable to load diary : " + ex.Message);
                logger.Log(LogLevel.Error, ex.StackTrace);
            }
            diary.Raw = docDiary;
            return diary;
        }

        // LOAD BEST
        private Best LoadBest(XmlNode node)
        {
            Best best = new Best();
            best.Books = LoadBooks(node.SelectSingleNode("books"));
            best.Songs = LoadSongs(node.SelectSingleNode("songs"));
            best.Movies = LoadMovies(node.SelectSingleNode("movies"));
            best.Albums = LoadAlbums(node.SelectSingleNode("albums"));
            best.Television = LoadTelevision(node.SelectSingleNode("television"));
            best.Events = LoadEvents(node.SelectSingleNode("events"));
            best.Pictures = LoadPictures(node.SelectSingleNode("pictures"));
            return best;
        }


        // LOAD BOOKS
        private List<Book> LoadBooks(XmlNode node)
        {
            List<Book> books = new List<Book>();
            if (node!=null)
            {
                XmlNodeList xmlListBooks = node.SelectNodes("book");
                foreach(XmlNode nodeBook in xmlListBooks)
                {
                    Book book = new Book();
                    book.Rank = int.Parse(nodeBook.Attributes["rank"].Value);
                    book.Title = nodeBook.Attributes["title"].Value;
                    book.Author = nodeBook.Attributes["author"].Value;
                    books.Add(book);
                }
            }
            return books;
        }

        // LOAD TELEVISION
        private List<Television> LoadTelevision(XmlNode node)
        {
            List<Television> tvshows = new List<Television>();
            if (node != null)
            {
                XmlNodeList xmlListShows = node.SelectNodes("tvshow");
                foreach (XmlNode nodeBook in xmlListShows)
                {
                    Television show = new Television();
                    show.Rank = int.Parse(nodeBook.Attributes["rank"].Value);
                    show.Title = nodeBook.Attributes["title"].Value;
                    tvshows.Add(show);
                }
            }
            return tvshows;
        }

        // LOAD MOVIES
        private List<Movie> LoadMovies(XmlNode node)
        {
            List<Movie> movies = new List<Movie>();
            if (node != null)
            {
                XmlNodeList xmlListBooks = node.SelectNodes("movie");
                foreach (XmlNode nodeMovie in xmlListBooks)
                {
                    Movie movie = new Movie();
                    movie.Rank = int.Parse(nodeMovie.Attributes["rank"].Value);
                    movie.Title = nodeMovie.Attributes["title"].Value;
                    movie.Year = nodeMovie.Attributes["year"].Value;
                    movies.Add(movie);
                }
            }
            return movies;
        }

        // LOAD ALBUMS
        private List<Album> LoadAlbums(XmlNode node)
        {
            List<Album> albums = new List<Album>();
            if (node != null)
            {
                XmlNodeList xmlListMovies = node.SelectNodes("album");
                foreach (XmlNode nodeAlbum in xmlListMovies)
                {
                    Album album = new Album();
                    album.Rank = int.Parse(nodeAlbum.Attributes["rank"].Value);
                    album.Title = nodeAlbum.Attributes["title"].Value;
                    album.Artist = nodeAlbum.Attributes["artist"].Value;
                    album.Year = nodeAlbum.Attributes["year"].Value;
                    albums.Add(album);
                }
            }
            return albums;
        }

        // LOAD WORKOUTS
        private List<Workout> LoadWorkouts(XmlNode node)
        {
            List<Workout> workouts = new List<Workout>();
            if (node != null)
            {
                XmlNodeList xmlList = node.SelectNodes("workout");
                foreach (XmlNode nodeWorkout in xmlList)
                {
                    Workout workout = new Workout();
                    workout.Title = nodeWorkout.Attributes["title"].Value;
                    workouts.Add(workout);
                }
            }
            return workouts;
        }

        // LOAD PICTURES
        private List<Picture> LoadPictures(XmlNode node)
        {
            List<Picture> pictures = new List<Picture>();
            if (node != null)
            {
                XmlNodeList xmlList = node.SelectNodes("picture");
                foreach (XmlNode nodePic in xmlList)
                {
                    Picture pic = new Picture();
                    pic.Rank = int.Parse(nodePic.Attributes["rank"].Value);
                    pic.Value = int.Parse(nodePic.Attributes["value"].Value);
                    pic.File = nodePic.InnerText;
                    pictures.Add(pic);
                }
            }
            return pictures;
        }

        // LOAD EVENTS
        private List<Event> LoadEvents(XmlNode node)
        {
            List<Event> events = new List<Event>();
            if (node != null)
            {
                XmlNodeList xmlList = node.SelectNodes("event");
                foreach (XmlNode nodeWorkout in xmlList)
                {
                    Event eventObj = new Event();
                    eventObj.Rank = int.Parse(nodeWorkout.Attributes["rank"].Value);
                    eventObj.Magnitude = int.Parse(nodeWorkout.Attributes["magnitude"].Value);
                    eventObj.Content = nodeWorkout.InnerText;
                    events.Add(eventObj);
                }
            }
            return events;
        }

        // LOAD BEST SONGS
        private List<Song> LoadSongs(XmlNode node)
        {
            List<Song> songs = new List<Song>();
            if (node != null)
            {
                XmlNodeList xmlList = node.SelectNodes("song");
                foreach (XmlNode nodeSong in xmlList)
                {
                    Song song = new Song();
                    song.Rank = int.Parse(nodeSong.Attributes["rank"].Value);
                    song.Title = nodeSong.Attributes["title"].Value;
                    song.Artist = nodeSong.Attributes["artist"].Value;
                    songs.Add(song);
                }
            }
            return songs;
        }

        // LOAD YEARS
        private List<Year> LoadYears(XmlElement element)
        {
            List<Year> years = new List<Year>();
            XmlNodeList xmlListYears = element.SelectNodes("years/year");
            foreach(XmlNode nodeYear in xmlListYears)
            {
                years.Add(LoadYear(nodeYear));
            }
            return years;
        }

        // LOAD YEAR
        private Year LoadYear(XmlNode node)
        {
            logger.Log(LogLevel.Info, "Loading section year");
            Year year = new Year();
            year.CurrentYear = int.Parse(node.Attributes["value"].Value);
            _currentDate = _currentDate.AddYears(year.CurrentYear - _currentDate.Year);

            year.Months = new List<Month>();
            year.Best = LoadBest(node);
            XmlNodeList xmlListMonths = node.SelectNodes("months/month");
            foreach (XmlNode nodeMonth in xmlListMonths)
            {
                year.Months.Add(LoadMonth(nodeMonth));
            }
            // LOAD YEAR BEST
            year.Best = LoadBest(node.SelectSingleNode("best"));

            return year;
        }

        // LOAD MONTH
        private Month LoadMonth(XmlNode node)
        {
            logger.Log(LogLevel.Info, "Loading section month");
            Month month = new Month();
            month.CurrentMonth = int.Parse(node.Attributes["value"].Value);
            _currentDate = _currentDate.AddMonths(month.CurrentMonth - _currentDate.Month);
            
            month.Days = new List<Day>();
            month.Best = LoadBest(node);
            XmlNodeList xmlListDays = node.SelectNodes("days/day");
            foreach (XmlNode nodeDay in xmlListDays)
            {
                month.Days.Add(LoadDay(nodeDay));
            }
            // LOAD MONTH BEST
            month.Best = LoadBest(node.SelectSingleNode("best"));

            return month;
        }

        // LOAD Day
        private Day LoadDay(XmlNode node)
        {
            Day day = new Day();
            day.Entry = new Entry() { Content = GetNodeSinglegValue(node, "entry") };
            day.Weekday = node.Attributes["weekday"].Value;
            day.CurrentDay = int.Parse(node.Attributes["value"].Value);
            _currentDate = _currentDate.AddDays(day.CurrentDay - _currentDate.Day);
            day.CurrentDate = _currentDate;

            // BOOKS
            day.Books = LoadBooks(node.SelectSingleNode("books"));

            // MOVIES
            day.Movies = LoadMovies(node.SelectSingleNode("movies"));

            // ALBUMS
            day.Albums = LoadAlbums(node.SelectSingleNode("albums"));

            // TELEVISION
            day.Television = LoadTelevision(node.SelectSingleNode("television"));

            // EVENTS
            day.Events = LoadEvents(node.SelectSingleNode("events"));

            // WORK
            day.Work = new Work() { Content = GetNodeSinglegValue(node, "work") };

            // WORKOUTS
            day.Workouts = LoadWorkouts(node.SelectSingleNode("workouts"));

            // PICS
            day.Pictures = LoadPictures(node.SelectSingleNode("pictures"));

            return day;
        }

        private string GetNodeSinglegValue(XmlNode node, string tag)
        {
            string result = "";
            XmlNode nodeTag = node.SelectSingleNode(tag);
            if (nodeTag != null)
            {
                result = nodeTag.InnerText;
            }
            return result;
        }
    }
}
